package com.czt.mail.limit;

/**
 * @author czt
 * @version 1.0
 * {@desc} 漏桶限流，平滑流量，可以防止突发流量引发的系统故障；但是无法处理突发流量，不建议用在速率变化大的场景
 * @date 2024/8/22 14:54
 */
public class LeakyBucketLimiter {

    /**
     * 桶的容量
     */
    private final long capacity;

    /**
     * 水流出的速度，即请求处理速度，单位秒
     */
    private final long rate;

    /**
     * 当前水量/请求数
     */
    private long water = 0L;

    private long lastTime = System.currentTimeMillis();

    public LeakyBucketLimiter(long capacity, long rate) {
        this.capacity = capacity;
        this.rate = rate;
    }

    public synchronized boolean limit() {
        long now = System.currentTimeMillis();
        //两次请求间隔内，应该流出的水滴数/应该处理的请求数
        long flowedWater = Math.round((now - lastTime) / 1000D * rate);
        System.out.println("now=" + now + ",lastTime=" + lastTime + ",flowedWater=" + flowedWater);
        water = Math.max(0, water - flowedWater);
        lastTime = now;
        if ((water + 1) <= capacity) {
            //水不满继续加水
            water++;
            return false;
        }else {
            //水满量
            return true;
        }
    }
}
